#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../include/list.h"

#define N 5 

typedef struct node_s {
	list_t list;	
	c_list_t c_list;
	dlist_t dlist;
	int a;
}node_t;


void check_isempty() {
	list_t head;
	c_list_t chead;
        dlist_t dhead;
	
	init_head(list_t, &head);
	init_head(c_list_t, &chead);
	init_head(dlist_t, &dhead);

	if (list_is_empty(&head)) {
		printf("right:list is empty\n");
	}		
	else {
		printf("wrong:list is not empty\n");
	} 

	if (c_list_is_empty(&chead)) {
		printf("right:clist is empty\n");
	}		
	else {
		printf("wrong:clist is not empty\n");
	} 
	
	if (dlist_is_empty(&dhead)) {
		printf("right:dlist is empty\n");
	}		
	else {
		printf("wrong:dlist is not empty\n");
	} 
	
}
void check_isnotempty() {
	list_t head;
	list_t entry;
	
	c_list_t chead;
	c_list_t centry;
	
	dlist_t dhead;
	dlist_t dentry;

	init_head(list_t, &head);
	init_head(c_list_t, &chead);
	init_head(dlist_t, &dhead);

	head.next = &entry;
	chead.next = &centry;
	dhead.next = &dentry;
	dhead.prev = &dentry;

	if (list_is_empty(&head)) {
		printf("wrong:list is empty\n");
	}		
	else {
		printf("right:list is not empty\n");
	} 
	if (c_list_is_empty(&chead)) {
		printf("wrong:clist is empty\n");
	}
	else {
		printf("right:clist is not empty\n");
	}
	if (dlist_is_empty(&dhead)) {
		printf("wrong:dlist is empty\n");
	}
	else {
		printf("right:dlist is not empty\n");
	}
}

void check_empty() {
	list_t head;
        list_t entry;

        c_list_t chead;
        c_list_t centry;

        dlist_t dhead;
        dlist_t dentry;

        init_head(list_t, &head);
        init_head(c_list_t, &chead);
        init_head(dlist_t, &dhead);

        head.next = &entry;
        chead.next = &centry;
        dhead.next = &dentry;
        dhead.prev = &dentry;	
	
	list_empty(&head);
	if (list_is_empty(&head)) {
                printf("right:list is empty\n");
        }
        else {
                printf("wrong:list is not empty\n");
		return ;
        }
		
	c_list_empty(&chead);
        if (c_list_is_empty(&chead)) {
                printf("right:clist is empty\n");
        }
        else {
                printf("wrong:clist is not empty\n");
		return ;
        }

	dlist_empty(&dhead);
        if (dlist_is_empty(&dhead)) {
                printf("right:dlist is empty\n");
        }
        else {
                printf("wrong:dlist is not empty\n");
		return ;
        }
}
void check_list_add_head() {
	list_t head;
	list_t * p;
	node_t nodes[N];
	node_t * pnode;
	int i = 0;	

	init_head(list_t, &head);
	
	for (i = 0 ; i < N; ++i) {
		nodes[i].a = i+1;
	}
	for (i = 0 ; i < N; ++i) {
		list_add_head(&head, &(nodes[i].list)); 
		list_add_head(&head, &(nodes[i].list)); 
	}
	p = head.next;
	for (i = N; p != NULL; --i) {
		pnode = entry(p, node_t, list);	
		if (pnode->a != i) {
			printf("wrong:list_add_head\n");
			return ;
		}
		printf("%d ", pnode->a);
		p = p->next;
	}	
	printf("right:list_add_head\n");
}
void check_list_add_tail() {
	list_t head;
        list_t * p;
        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(list_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
                list_add_tail(&head, &nodes[i].list);
                list_add_tail(&head, &nodes[i].list);
        }
        p = head.next;
        for (i = 1; p != NULL; ++i) {
                pnode = entry(p, node_t, list);
                if (pnode->a != i) {
                        printf("wrong:list_add_tail\n");
                        return ;
                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        printf("right:list_add_tail\n");
}

void check_list_insert(){
	list_t head;
        list_t * p;
        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(list_t, &head);


        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
	list_add_head(&head, &nodes[0].list);
		
        for (i = 1 ; i < N; ++i) {
                list_insert(&nodes[0].list, &(nodes[i].list));
        }
        p = head.next;
	
	pnode = entry(p , node_t, list);
	if (pnode->a != 1) {
		printf("wrong:list_insert\n");
		return ;
	}
	printf("%d ", pnode->a);
	p = p->next;
        for (i = N; p != NULL; --i) {
                pnode = entry(p, node_t, list);
		if (pnode->a != i) {
			printf("wrong:list_insert\n");
			return ;
	
		}
                printf("%d ", pnode->a);
                p = p->next;
        }
	printf("right:list_insert\n");
}

void check_list_del() {
	list_t head;
        list_t * p;
        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(list_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
                list_add_tail(&head, &nodes[i].list);
        }
	
	list_del(&head, &nodes[0].list);
	list_del(&head, &nodes[2].list);	
	
	p = head.next;
        while (p != NULL) {
                pnode = entry(p, node_t, list);
                if (pnode->a == 1) {
                        printf("wrong:list_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        }
	printf("\t");
	p = head.next;
        while (p != NULL) {
                pnode = entry(p, node_t, list);
                if (pnode->a == 3) {
                        printf("wrong:list_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        } 
	printf("right:list_del\n");	
}
void check_list_is_exist() {
	list_t head;
        list_t * p;
        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(list_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
		if (list_is_exist(&head, &nodes[i].list)) {
			printf("wrong1:list_is_exist\n");
			return ;
		}		
                list_add_tail(&head, &nodes[i].list);
		if (!list_is_exist(&head, &nodes[i].list)) {
			printf("wrong2:list_is_exist\n");
			return ;
		}
	}
	printf("right:list_is_exist\n");
}

void check_c_list_add_head() {
	c_list_t head;
        c_list_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;

        init_head(list_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
	for (i = 0; i < N; ++i) {
		c_list_add_head(&head, &(nodes[i].c_list));
		c_list_add_head(&head, &(nodes[i].c_list));
	} 
        p = head.next;
        for (i = N; p != &head; --i) {
                pnode = entry(p, node_t, c_list);
                if (pnode->a != i) {
                        printf("wrong:c_list_add_head\n");
                        return ;
                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        printf("right:c_list_add_head\n");		
}

void check_c_list_add_tail() {
	c_list_t head;
        c_list_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(c_list_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
                c_list_add_tail(&head, &(nodes[i].c_list));
                c_list_add_tail(&head, &(nodes[i].c_list));
        }
        p = head.next;
        for (i = 1; p != &head; ++i) {
                pnode = entry(p, node_t, c_list);
                if (pnode->a != i) {
                        printf("wrong:c_list_add_tail\n");
                        return ;
                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        printf("right:c_list_add_tail\n");	
}

void check_c_list_insert() {
	c_list_t head;
        c_list_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(c_list_t, &head);


        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        c_list_add_head(&head, &(nodes[0].c_list));

        for (i = 1 ; i < N; ++i) {
                c_list_insert(&(nodes[0].c_list), &(nodes[i].c_list));
        }
        p = head.next;

        pnode = entry(p , node_t, c_list);
        if (pnode->a != 1) {
                printf("wrong:c_list_insert\n");
                return ;
        }
        printf("%d ", pnode->a);
        p = p->next;
        for (i = N; p != &head; --i) {
                pnode = entry(p, node_t, c_list);
                if (pnode->a != i) {
                        printf("wrong:c_list_insert\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        printf("right:c_list_insert\n");	
}

void check_c_list_del() {
	c_list_t head;
        c_list_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;

        init_head(c_list_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
                c_list_add_tail(&head, &nodes[i].c_list);
        }

        c_list_del(&head, &nodes[0].c_list);
        c_list_del(&head, &nodes[2].c_list);

        p = head.next;
        while (p != &head) {
                pnode = entry(p, node_t, c_list);
                if (pnode->a == 1) {
                        printf("wrong:c_list_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        printf("\t");
        p = head.next;
        while (p != &head) {
                pnode = entry(p, node_t, c_list);
                if (pnode->a == 3) {
                        printf("wrong:c_list_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        printf("right:c_list_del\n");	
}

void check_c_list_is_exist() {
	c_list_t head;
        c_list_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(c_list_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
		if (c_list_is_exist(&head, &nodes[i].c_list)) {
			printf("wrong1:c_list_is_exist\n");
			return ;
		}
                c_list_add_tail(&head, &(nodes[i].c_list));
		if (!c_list_is_exist(&head, &nodes[i].c_list)) {
			printf("wrong2:c_list_is_exist\n");
			return;
		}
        }
	printf("right:c_list_is_exist\n");
}
void check_dlist_add_head() {
	dlist_t head;
        dlist_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;

        init_head(dlist_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0; i < N; ++i) {
                dlist_add_head(&head, &(nodes[i].dlist));
                dlist_add_head(&head, &(nodes[i].dlist));
        }
        p = head.next;
        for (i = N; p != &head; --i) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a != i) {
                        printf("wrong:dlist_add_head\n");
                        return ;
                }
                printf("%d ", pnode->a);
                p = p->next;
        }
	p = head.prev;
	for (i = 1; p != &head; ++i) {
		pnode = entry(p, node_t, dlist);
                if (pnode->a != i) {
                        printf("wrong:dlist_add_head\n");
                        return ;
                }
                printf("%d ", pnode->a);
                p = p->prev;
	}
        printf("right:dlist_add_head\n");	
}

void check_dlist_add_tail() {
	dlist_t head;
        dlist_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(dlist_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
                dlist_add_tail(&head, &(nodes[i].dlist));
                dlist_add_tail(&head, &(nodes[i].dlist));
        }
        p = head.next;
        for (i = 1; p != &head; ++i) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a != i) {
                        printf("wrong:dlist_add_tail\n");
                        return ;
                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        p = head.prev;
        for (i = N; p != &head; --i) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a != i) {
                        printf("wrong:dlist_add_tail\n");
                        return ;
                }
                printf("%d ", pnode->a);
                p = p->prev;
        }
        printf("right:dlist_add_tail\n");
}

void check_dlist_insert() {
	dlist_t head;
        dlist_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(dlist_t, &head);


        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        dlist_add_head(&head, &(nodes[0].dlist));

        for (i = 1 ; i < N; ++i) {
                dlist_insert(&(nodes[0].dlist), &(nodes[i].dlist));
        }
        p = head.next;
        pnode = entry(p , node_t, dlist);
        if (pnode->a != 1) {
                printf("wrong:dlist_insert\n");
                return ;
        }
        printf("%d ", pnode->a);
        p = p->next;
        for (i = N; p != &head; --i) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a != i) {
                        printf("wrong:dlist_insert\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        p = head.prev;
        for (i = 2; p != &head; ++i) {
                pnode = entry(p, node_t, dlist);
                if (p->prev != &head && pnode->a != i) {
                        printf("wrong:dlist_insert\n");
                        return ;
                }
		else if (p->prev == &head && pnode->a != 1) {
                        printf("wrong:dlist_insert\n");
                        return ;
		}
                printf("%d ", pnode->a);
                p = p->prev;
        }
        printf("right:dlist_insert\n");
}

void check_dlist_del() {
	dlist_t head;
        dlist_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;

        init_head(dlist_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
                dlist_add_tail(&head, &nodes[i].dlist);
        }

        dlist_del(&head, &nodes[0].dlist);
        dlist_del(&head, &nodes[2].dlist);

        p = head.next;
        while (p != &head) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a == 1) {
                        printf("wrong:dlist_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        printf("\t");
        p = head.next;
        while (p != &head) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a == 3) {
                        printf("wrong:dlist_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->next;
        }
        p = head.prev;
        while (p != &head) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a == 1) {
                        printf("wrong:dlist_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->prev;
        }
        printf("\t");
        p = head.prev;
        while (p != &head) {
                pnode = entry(p, node_t, dlist);
                if (pnode->a == 3) {
                        printf("wrong:dlist_del\n");
                        return ;

                }
                printf("%d ", pnode->a);
                p = p->prev;
        }
        printf("right:dlist_del\n");
}
void check_dlist_is_exist() {
	dlist_t head;
        dlist_t * p;

        node_t nodes[N];
        node_t * pnode;
        int i = 0;
        init_head(dlist_t, &head);

        for (i = 0 ; i < N; ++i) {
                nodes[i].a = i+1;
        }
        for (i = 0 ; i < N; ++i) {
		if (dlist_is_exist(&head, &nodes[i].dlist)) {
			printf("wrong1:dlist_is_exist\n");	
			return ;	
		}
                dlist_add_tail(&head, &(nodes[i].dlist));
		if (!dlist_is_exist(&head, &nodes[i].dlist)) {
			printf("wrong2:dlist_is_exist\n");
			return ;
		}
        }
	printf("right:dlist_is_exist\n");
}
int main() {
	check_isempty();
	check_isnotempty();	

	check_list_add_head();
	check_list_add_tail();
	check_list_insert();
	check_list_del();
	check_list_is_exist();

	check_c_list_add_head();
	check_c_list_add_tail();
	check_c_list_insert();
	check_c_list_del();	
	check_c_list_is_exist();
	
	check_dlist_add_head();
	check_dlist_add_tail();
	check_dlist_insert();
	check_dlist_del();		
	check_dlist_is_exist();

	check_empty();
	return 0;
}


